package com.lims.algorithm.algset.graph.expression;

import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * <功能简述> 实例：业务bean为包含一个字符串值的bean，自定义处理逻辑对图进行处理
 * <p>
 * *********实际业务bean和处理逻辑根据业务场景自定义即可
 *
 * @author lims
 * @date 2021-05-02 16:31
 */
public class ExpressionDgEngine extends DgGraphEngine<ExpressionBean> {
    /**
     * 日志
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(ExpressionDgEngine.class);

    /**
     * 构造函数，初始化数组大小为2，无实际意义，一般不使用
     *
     * @param n
     */
    public ExpressionDgEngine(int n) {
        super(2);
    }

    /**
     * 构建表达式处理DAG的构造函数
     *
     * @param vertexs 顶点集合
     * @param edgesIn 边集合
     */
    public ExpressionDgEngine(List<ExpressionBean> vertexs, List<DgEdgeKvBean> edgesIn) {
        super(vertexs, edgesIn);
        /*if (CollectionUtils.isEmpty(vertexs)) {
            LOGGER.info("构建处理表达式有向无环图失败--没有可用顶点");
            throw new RuntimeException("构建处理表达式有向无环图失败--没有可用顶点");
        }
        ExpressionDgEngine dgGraphEngine = new ExpressionDgEngine(2);
        // 初始化访问标记数组
        dgGraphEngine.fixIsVisited(vertexs.size());
        // 依次添加顶点
        vertexs.forEach(dgGraphEngine::addVer);
        // 添加边 默认权重设置为1
        edgesIn.forEach(edge -> {
            dgGraphEngine.addEdge(
                    indexOfVertexsByKey(edge.getStartEdgePoint()),
                    indexOfVertexsByKey(edge.getEndEdgePoint()),
                    1
            );
        });*/
        // 对所有顶点是否为叶子顶点属性进行设置
        setVerIsLeaf();
    }


    /**
     * 获取反向依赖处理顶点的函数接口逻辑实现
     * 叶子顶点时，给值追加后缀“leaf”
     * 非叶子顶点时，将所有子顶点的值追加给自己作为值
     *
     * @return
     */
    public Consumer<ExpressionBean> getRvsProssConsumerExecute() {
        return exp -> {
            // 叶子顶点处理逻辑
            if (exp.getIsLeaf()) {
                // 给顶点的值追加后缀“leaf”
                exp.setExpressionValue(exp.getExpressionValue().concat("：leaf"));
            } else {
                // 非叶子结点，将所有子顶点的值追加到后面
                List<Integer> pointVers = getPointVers(exp.getKey());
                // 依赖自己的子顶点的值追加到一起
                StringBuilder strAppend = new StringBuilder();
                strAppend.append(exp.getExpressionValue());
                pointVers.stream().forEach(p -> {
                    strAppend.append("--");
                    strAppend.append(vertexs.get(p).data.getExpressionValue());
                });
                exp.setExpressionValue(strAppend.toString());
            }
        };
    }


    // 实例
    public static void main(String[] args) {
        // 构建图
        /**
         * *        ____D____H
         * *       /      ___F
         * *      B      /
         * *     / \____E
         * *    /       \___G
         * *   A
         * *    \_C
         * *
         */

        // 手动初始化8个顶点
        ExpressionBean a = new ExpressionBean.Builder()
                .setKey("a").setExpressionValue("aValue").build();
        ExpressionBean b = new ExpressionBean.Builder()
                .setKey("b").setExpressionValue("bValue").build();
        ExpressionBean c = new ExpressionBean.Builder()
                .setKey("c").setExpressionValue("cValue").build();
        ExpressionBean d = new ExpressionBean.Builder()
                .setKey("d").setExpressionValue("dValue").build();
        ExpressionBean e = new ExpressionBean.Builder()
                .setKey("e").setExpressionValue("eValue").build();
        ExpressionBean f = new ExpressionBean.Builder()
                .setKey("f").setExpressionValue("fValue").build();
        ExpressionBean g = new ExpressionBean.Builder()
                .setKey("g").setExpressionValue("gValue").build();
        ExpressionBean h = new ExpressionBean.Builder()
                .setKey("h").setExpressionValue("hValue").build();

        // 添加顶点到顶点集合
        List<ExpressionBean> vertexs = new ArrayList<>();
        vertexs.add(a);
        vertexs.add(b);
        vertexs.add(c);
        vertexs.add(d);
        vertexs.add(e);
        vertexs.add(f);
        vertexs.add(g);
        vertexs.add(h);

        // 构建有向边 <a,b><a,c><b,d><b,e><d,h><e,f><e,g>
        List<DgEdgeKvBean> edgesIn = new ArrayList<>();
        edgesIn.add(new DgEdgeKvBean("a", "b"));
        edgesIn.add(new DgEdgeKvBean("a", "c"));
        edgesIn.add(new DgEdgeKvBean("b", "d"));
        edgesIn.add(new DgEdgeKvBean("b", "e"));
        edgesIn.add(new DgEdgeKvBean("d", "h"));
        edgesIn.add(new DgEdgeKvBean("e", "f"));
        edgesIn.add(new DgEdgeKvBean("e", "g"));

        // 构件图
        ExpressionDgEngine dgEngine = new ExpressionDgEngine(vertexs, edgesIn);
        // 打印头顶点的值
        System.out.println(dgEngine.vertexs.get(0).data.getExpressionValue());
        // 执行反向依赖处理
        dgEngine.reverseProcessDepend(dgEngine.getRvsProssConsumerExecute());

        // 打印处理后头顶点的值
        System.out.println(dgEngine.vertexs.get(0).data.getExpressionValue());
    }
}
